package com.herenit.order_model.utils.rabbitmq;

import com.herenit.order_model.constant.MessageConstant;
import com.herenit.order_model.enums.ExceptionEnums;
import com.herenit.order_model.exception.MyException;
import com.herenit.order_model.model.Message;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Random;

@Component
public class RabbitMQUtils {

    private static final String PRIOR = "prior_";

    private static final String NORMAL = "normal_";

    private static Message rtnMessage;

    // 将要发送的数据放入map 把map发送进队列
    private static HashMap<String, Object> map = new HashMap();

    @Autowired
    private RabbitAdmin rabbitAdmin;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 发送到一般队列
     * @param institution 机构名
     * @param message      消息内容
     */
    public void send(String institution, String message) {
        Properties properties = rabbitAdmin.getQueueProperties(NORMAL + institution);
        // 该机构的消息队列不存在时
        if (properties == null) {
            // 声明队列与交换机
            declareExchangeAndQueue(institution);
        }
        // 数据放在map中 发送map进消息队列
        map.put("recordId", null);
        map.put("messageBody", message);
        rabbitTemplate.convertAndSend("", NORMAL + institution, map);
    }

    /**
     * 发送到优先队列
     * @param institution 机构名
     * @param message      消息内容
     * @param recordId     记录id
     */
    public void sendPrior(String institution, String message, Long recordId) {
        Properties properties = rabbitAdmin.getQueueProperties(PRIOR + institution);
        // 该机构的消息队列不存在时
        if (properties == null) {
            // 声明队列与交换机
            declareExchangeAndQueue(institution);
        }
        // 数据放在map中 发送map进消息队列
        map.put("recordId", recordId);
        map.put("messageBody", message);
        try {
            rabbitTemplate.convertAndSend("", PRIOR + institution, map);
        } catch (AmqpException e) {
            throw new MyException(ExceptionEnums.RABBIT_SEND_ERROR);
        }
    }

    public Message consume(String institution, String doctor) {
        if (rabbitAdmin.getQueueProperties(PRIOR + institution) == null) {
            declareExchangeAndQueue(institution);
        }
        // 存放从rabbitmq获取的对象
        Map receive;
        try {
            // 尝试从优先队列获取消息
            receive = (Map) rabbitTemplate.receiveAndConvert(PRIOR + institution);
            if (receive == null) {
                // 从一般队列获取消息
                receive = (Map) rabbitTemplate.receiveAndConvert(NORMAL + institution);
            }
        } catch (AmqpException e) {
            throw new MyException(ExceptionEnums.RABBIT_RECEIVE_ERROR);
        }
        // 两次拉取都为空 队列中已无消息
        if (receive == null) {
            rtnMessage = new Message("0", "队列为空", receive);
            return rtnMessage;
        }
        // 模拟消费失败 随机发生 消费失败 code 为 0
        int random = new Random().nextInt(100);
        if (random < 50) {
            rtnMessage = new Message("0", MessageConstant.NETWORK_REASON, receive);
            if (random > 10) {
                rtnMessage.setMessage(MessageConstant.RETURN_REASON);
            }
            if (random > 25) {
                rtnMessage.setMessage(MessageConstant.DEAL_WITH_REASON);
            }
            if (random > 40) {
                rtnMessage.setMessage(MessageConstant.OTHER_REASON);
            }
            return rtnMessage;
        }
        // 模拟消费成功
        rtnMessage = new Message("200", MessageConstant.SUCCESS, receive);
        return rtnMessage;
    }

    private void declareExchangeAndQueue(String institution) {
//        DirectExchange exchange = new DirectExchange(EXCHANGE + institution, false, false);
        Queue priorQueue = new Queue(PRIOR + institution, false, false, false);
        Queue herenQueue = new Queue(NORMAL + institution, false, false, false);
//        rabbitAdmin.declareExchange(exchange);
        rabbitAdmin.declareQueue(priorQueue);
        rabbitAdmin.declareQueue(herenQueue);
        // 路由 直接用队列名
//        rabbitAdmin.declareBinding(BindingBuilder.bind(priorQueue).to(exchange).with(priorQueue.getName()));
//        rabbitAdmin.declareBinding(BindingBuilder.bind(herenQueue).to(exchange).with(herenQueue.getName()));
    }
}
